package spider

import (
	"asocrawler/conf"
	"asocrawler/db"
	"asocrawler/tool"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"runtime/debug"
	"time"
)

const (
	DouYinApiUrl = "https://www.douyin.com/aweme/v1/web/channel/hotspot"
)

type DouYinSpider struct {
	ChannelName  string
	TimeInterval int
	Platform     string
}

func NewDouYinSpider() (v *DouYinSpider) {
	v = &DouYinSpider{
		ChannelName:  "抖音",
		Platform:     "抖音",
		TimeInterval: 2,
	}
	return
}

func (this DouYinSpider) Run() {
	go func() {
		this.run()
	}()
}
func (this *DouYinSpider) Println(v ...interface{}) {
	var str = fmt.Sprintf("[%s]-[%s]", this.ChannelName, this.Platform)
	if conf.Conf.Debug.Switch {
		str += "-[Debug]"
	}
	log.Println(str, fmt.Sprintln(v...))
}

type DouYinResult struct {
	StatusCode int `json:"status_code"`
	HasMore    int `json:"has_more"`
	AwemeList  []struct {
		AwemeId      string `json:"aweme_id"`       // 视频id
		CreateTime   int64  `json:"create_time"`    // 视频发布时间 秒级时间戳
		AuthorUserId int    `json:"author_user_id"` // 视频作者id
		Author       struct {
			NickName    string `json:"nickName"` // 作者昵称
			AvatarThumb struct {
				UrlList []string `json:"url_list"` //头像
			} `json:"avatar_thumb"`
		} `json:"author"`
		Desc       string `json:"desc"`      // 视频标题
		ShareUrl   string `json:"share_url"` // 视频链接
		Statistics struct {
			CollectCount int `json:"collect_count"` // 收藏数
			CommentCount int `json:"comment_count"` // 评论数
			DiggCount    int `json:"digg_count"`    // 点赞数
			ShareCount   int `json:"share_count"`   // 分享数
			PlayCount    int `json:"play_count"`    // 播放数
		} `json:"statistics"`
		Video struct {
			Cover struct {
				UrlList []string `json:"url_list"` //视频封面
			} `json:"cover"`
		} `json:"video"`
	} `json:"aweme_list"`
}

func (this *DouYinSpider) collectVideoData(date string) (rs []db.NewRankVideoResult, err error) {
	tryTimes := 0
	client := &http.Client{}

	//data := url.Values{}
	//data.Add("device_platform", "")
	//data.Add("aid", "6383")
	//data.Add("channel", "channel_pc_web")
	//data.Add("tag_id", "")
	//data.Add("count", "10")
	//data.Add("Seo-Flag", "0")
	//data.Add("channel_id", "99")
	//data.Add("version_code", "170400")
	//data.Add("version_name", "17.4.0")
	//data.Add("cookie_enabled", "true")
	//data.Add("screen_width", "1920")
	//data.Add("screen_height", "1080")
	//data.Add("browser_language", "zh-CN")
	//data.Add("browser_platform", "Win32")
	//data.Add("browser_name", "Chrome")
	//data.Add("browser_version", "78.0.3904.108")
	//data.Add("browser_online", "true")
	//data.Add("engine_name", "Blink")
	//data.Add("engine_version", "78.0.3904.108")
	//data.Add("os_name", "Windows")
	//data.Add("os_version", "10")
	//data.Add("cpu_core_num", "16")
	//data.Add("device_memory", "8")
	//data.Add("platform", "PC")
	//data.Add("downlink", "10")
	//data.Add("effective_type", "4g")
	//data.Add("round_trip_time", "50")
	//data.Add("webid", "7074784175794587147")
	//data.Add("msToken", "evP_1Pc1j3iE76oyAM2dkh10q4E9XO7x5Pq5oo_3smxnClGRY6X_-lnaY40V0DPNqQS7bLvm5hm07ChcqemUzWfixvPwNWKkpciMMKB7IMOAvpwwfTy0FA==")
	//data.Add("X-Bogus", "DFSzsdVLm6iANVuqSf1qrr4ELVVM")
	//data.Add("_signature", "_02B4Z6wo00001Yf.t.wAAIDCNw5bNp8igFmH-7NAAANPFeMElEvROWv80PxRz60z3BTaw0tJITm6nt0O7L.C6MdkSH42KN3IWinMaJ3-ZuRptyZ0esPL8h9YOPmvzokKN8hHV-CO5OAuZJSGd2")

re:

	req, err := http.NewRequest("GET", DouYinApiUrl, nil)
	if err != nil {
		return
	}

	req.Header.Set("referer", "https://www.douyin.com/hot")

	resp, err := client.Do(req)
	if err != nil {
		time.Sleep(1 * time.Second)
		return
	}

	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	var p DouYinResult
	err = json.Unmarshal(b, &p)
	if err != nil {
		this.Println("collectVideoData error,err=", err, string(b))
		return
	}

	if p.StatusCode != 0 {
		if tryTimes < 10 {
			this.Println("collectVideoData p.StatusCode != 0,尝试重新请求...tryTimes：", tryTimes)
			tryTimes++
			time.Sleep(500 * time.Millisecond)
			goto re
		}
		err = errors.New("抖音视频 p.StatusCode != 0,p=" + string(b))
		return
	}

	vPlatform := this.Platform

	for _, d := range p.AwemeList {

		videoId := d.AwemeId + "-" + vPlatform
		publishTime := time.Unix(d.CreateTime, 0).Format("2006-01-02 15:04:05")

		// 作者id
		userId := fmt.Sprint(d.AuthorUserId) + "-" + vPlatform

		// 作者头像
		var userAvatar string
		if len(d.Author.AvatarThumb.UrlList) > 0 {
			userAvatar = d.Author.AvatarThumb.UrlList[0]
		}

		// 视频封面
		var cover string
		if len(d.Video.Cover.UrlList) > 0 {
			cover = d.Video.Cover.UrlList[0]
		}

		r := db.NewRankVideoResult{
			VideoId:       videoId,
			VideoTitle:    d.Desc,
			VideoPlatform: vPlatform,
			CoverUrl:      cover,
			PublishTime:   publishTime,
			OriginUrl:     d.ShareUrl,

			UserId:       userId,
			UserAvatar:   userAvatar,
			UserNickName: d.Author.NickName,
			//UserType:     ",

			TotalShareCount:   d.Statistics.ShareCount,
			TotalCommentCount: d.Statistics.CommentCount,
			TotalDiggCount:    d.Statistics.DiggCount,
			TotalViewCount:    d.Statistics.PlayCount, // 接口全为0 原因未知

			Date: date,
		}

		rs = append(rs, r)
	}
	return
}

func (this *DouYinSpider) Collect(date string) (bool, error) {
	rs, err := this.collectVideoData(date)
	if err != nil {
		return false, err
	}

	if len(rs) == 0 {
		this.Println("DouYinSpider data len = 0")
		tool.SendWarn("ASO报警-抖音 爬虫报错", "ASO报警-newRank-抖音 抖音爬虫报错,错误信息：无数据")
	} else {
		err := db.SaveNewRankData(rs)
		if err != nil {
			return false, err
		}
	}
	return true, nil

}

func (this *DouYinSpider) run() {
	defer func() {
		if err := recover(); err != nil {
			errMsg := string(debug.Stack())
			this.Println("[崩溃]err=", err, errMsg)
		}
	}()
	if conf.Conf.Debug.Switch {
		for _, fDate := range conf.Conf.Debug.DateList {
			this.Println("日期:", fDate, "开始采集数据...")
			succ, err := this.Collect(fDate)
			if succ {
				this.Println("日期:", fDate, "采集数据完成")
			} else {
				if err == nil {
					this.Println("日期:", fDate, "数据未更新")
				} else {
					this.Println("日期:", fDate, "出现错误err:", err)
				}
			}
		}
	} else {
	re:
		fDate := time.Now().Format("2006-01-02")
		this.GetDataByDate(fDate)
		time.Sleep(time.Duration(this.TimeInterval) * time.Hour)
		goto re
	}
}

func (this *DouYinSpider) GetDataByDate(date string) {
	this.Println("日期:", date, "开始采集数据...")
	success, err := this.Collect(date)
	if err != nil {
		tool.SendWarn("ASO报警-抖音 爬虫报错", "ASO报警-抖音 爬虫报错,错误信息："+err.Error())
		this.Println("日期:", date, "采集失败 err=", err)
	} else {
		if success {
			this.Println("日期:", date, "采集数据完成 稍后再次采集...")
		} else {
			this.Println("日期:", date, "数据未更新 稍后重新采集...")
		}
	}
}
